/***************************************************************************
 *   oboe.math.Rotator							 *
 *   Copyright (C) 2011 by Felipe Manga					*
 *   lufeboma@gmail.com							*
 *									 *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the	   *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to	*
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:						 *
 *									 *
 *   The above copyright notice and this permission notice shall be	*
 *   included in all copies or substantial portions of the Software.	   *
 *									 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,	   *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF	*
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR	 *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.					   *
 ***************************************************************************/

package oboe.math;

/**
 * This class is for rotating various 3D points on the X/Y/Z axis. 
 * @author FelipeManga
 * 
 */
class Rotator extends Number3D
{
public var xvx : Float;
public var xvy : Float;
public var xvz : Float;
public var yvx : Float;
public var yvy : Float;
public var yvz : Float;
public var zvx : Float;
public var zvy : Float;
public var zvz : Float;

/**
 * Class cosntructor 
 * @param x initial X axis rotation in radians
 * @param y initial Y axis rotation in radians
 * @param z initial Z axis rotation in radians
 * 
 */
public function new(x:Float, y:Float, z:Float)
{
	super(x, y, z);
	this.update();
}

/**
 * Before calling the apply functions, the rotator must be updated if the X, Y or Z angle has changed. 
 */
public function update() : Void {
	this.mod( 6.283185 );
	
	var cosxr : Float, cosyr : Float, coszr : Float, sinxr : Float, sinyr : Float, sinzr : Float;
	cosxr = Math.cos(x); cosyr = Math.cos(y); coszr = Math.cos(z);
	sinxr = Math.sin(x); sinyr = Math.sin(y); sinzr = Math.sin(z);

	xvx = (cosyr * coszr); xvy = (sinxr * sinyr * coszr - cosxr * sinzr); xvz = (cosxr * sinyr * coszr + sinxr * sinzr);
	yvx = (cosyr * sinzr); yvy = (cosxr * coszr + sinxr * sinyr * sinzr); yvz = (-sinxr * coszr + cosxr * sinyr * sinzr);
	zvx = (-sinyr); zvy = (sinxr * cosyr); zvz = (cosxr * cosyr);
}

/**
 * Applies a rotation without modifying the input vector 
 * @param vec input vector
 * @param out output vector
 * 
 */
public function constapply( vec : Float3D, out : Float3D ) : Void {
	out.x = vec.x * xvx + vec.y * xvy + vec.z * xvz;
	out.y = vec.x * yvx + vec.y * yvy + vec.z * yvz;
	out.z = vec.x * zvx + vec.y * zvy + vec.z * zvz;
}	

/**
 * Applies a rotation to a vector 
 * @param vec vector to rotate
 * 
 */
public function apply( vec : Float3D ) : Void {
	vec.copy2( 
	vec.x * xvx + vec.y * xvy + vec.z * xvz, 
	vec.x * yvx + vec.y * yvy + vec.z * yvz,
	vec.x * zvx + vec.y * zvy + vec.z * zvz
	);
}
}